using System.Drawing.Imaging;

namespace PhotoYS
{
    public partial class Form1 : Form
    {
        private string selectedFolderPath = string.Empty;
        private List<string> imageFiles = new List<string>();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog folderDialog = new FolderBrowserDialog())
            {
                folderDialog.Description = "选择包含图片的文件夹";
                folderDialog.ShowNewFolderButton = false;

                if (folderDialog.ShowDialog() == DialogResult.OK)
                {
                    selectedFolderPath = folderDialog.SelectedPath;
                    txtFolderPath.Text = selectedFolderPath;
                    LoadImageFiles();
                }
            }
        }

        private void LoadImageFiles()
        {
            listBoxFiles.Items.Clear();
            imageFiles.Clear();

            if (string.IsNullOrEmpty(selectedFolderPath) || !Directory.Exists(selectedFolderPath))
            {
                lblStatus.Text = "请选择有效的文件夹";
                return;
            }

            string[] extensions = { "*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.tiff" };
            
            foreach (string ext in extensions)
            {
                string[] files = Directory.GetFiles(selectedFolderPath, ext, SearchOption.TopDirectoryOnly);
                imageFiles.AddRange(files);
            }

            if (imageFiles.Count > 0)
            {
                foreach (string file in imageFiles)
                {
                    FileInfo fi = new FileInfo(file);
                    string displayText = $"{Path.GetFileName(file)} ({GetFileSizeString(fi.Length)})";
                    listBoxFiles.Items.Add(displayText);
                }
                
                lblStatus.Text = $"找到 {imageFiles.Count} 个图片文件";
                btnCompress.Enabled = true;
            }
            else
            {
                lblStatus.Text = "文件夹中没有找到图片文件";
                btnCompress.Enabled = false;
            }
        }

        private string GetFileSizeString(long bytes)
        {
            if (bytes < 1024)
                return $"{bytes} B";
            else if (bytes < 1024 * 1024)
                return $"{bytes / 1024.0:F2} KB";
            else
                return $"{bytes / (1024.0 * 1024.0):F2} MB";
        }

        private async void btnCompress_Click(object sender, EventArgs e)
        {
            if (imageFiles.Count == 0)
            {
                MessageBox.Show("没有图片文件需要压缩", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            btnCompress.Enabled = false;
            btnSelectFolder.Enabled = false;
            
            long targetSizeKB = (long)numTargetSize.Value;
            long targetSizeBytes = targetSizeKB * 1024;

            progressBar.Maximum = imageFiles.Count;
            progressBar.Value = 0;

            int successCount = 0;
            int skipCount = 0;
            int errorCount = 0;

            await Task.Run(() =>
            {
                for (int i = 0; i < imageFiles.Count; i++)
                {
                    string imagePath = imageFiles[i];
                    string fileName = Path.GetFileName(imagePath);
                    
                    this.Invoke(new Action(() =>
                    {
                        lblStatus.Text = $"正在处理: {fileName} ({i + 1}/{imageFiles.Count})";
                        progressBar.Value = i + 1;
                    }));

                    try
                    {
                        FileInfo fileInfo = new FileInfo(imagePath);
                        
                        if (fileInfo.Length <= targetSizeBytes)
                        {
                            skipCount++;
                            continue;
                        }

                        CompressImage(imagePath, targetSizeBytes);
                        successCount++;
                    }
                    catch (Exception ex)
                    {
                        errorCount++;
                        this.Invoke(new Action(() =>
                        {
                            listBoxFiles.Items[i] = $"{fileName} - 压缩失败: {ex.Message}";
                        }));
                    }
                }
            });

            LoadImageFiles();
            
            string resultMessage = $"压缩完成！\n成功: {successCount} 个\n跳过(已小于目标大小): {skipCount} 个";
            if (errorCount > 0)
            {
                resultMessage += $"\n失败: {errorCount} 个";
            }
            
            MessageBox.Show(resultMessage, "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            
            btnCompress.Enabled = true;
            btnSelectFolder.Enabled = true;
            lblStatus.Text = "压缩完成";
        }

        private void CompressImage(string imagePath, long targetSizeBytes)
        {
            using (Image originalImage = Image.FromFile(imagePath))
            {
                string tempPath = Path.Combine(Path.GetTempPath(), Path.GetFileName(imagePath));
                
                try
                {
                    int quality = 95;
                    long resultSize = 0;
                    int width = originalImage.Width;
                    int height = originalImage.Height;
                    double scale = 1.0;

                    while (quality >= 10)
                    {
                        using (Bitmap bitmap = new Bitmap((int)(width * scale), (int)(height * scale)))
                        {
                            using (Graphics graphics = Graphics.FromImage(bitmap))
                            {
                                graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                                graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                graphics.DrawImage(originalImage, 0, 0, bitmap.Width, bitmap.Height);
                            }

                            ImageCodecInfo? jpegCodec = GetEncoderInfo("image/jpeg");
                            if (jpegCodec != null)
                            {
                                EncoderParameters encoderParams = new EncoderParameters(1);
                                encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)quality);
                                bitmap.Save(tempPath, jpegCodec, encoderParams);
                            }
                            else
                            {
                                bitmap.Save(tempPath, ImageFormat.Jpeg);
                            }
                        }

                        FileInfo tempFileInfo = new FileInfo(tempPath);
                        resultSize = tempFileInfo.Length;

                        if (resultSize <= targetSizeBytes)
                        {
                            break;
                        }

                        if (resultSize > targetSizeBytes * 2)
                        {
                            scale *= 0.9;
                            if (scale < 0.1) scale = 0.1;
                        }
                        else if (resultSize > targetSizeBytes * 1.5)
                        {
                            quality -= 10;
                        }
                        else
                        {
                            quality -= 5;
                        }
                    }

                    if (File.Exists(tempPath))
                    {
                        originalImage.Dispose();
                        File.Delete(imagePath);
                        File.Move(tempPath, imagePath);
                    }
                }
                catch
                {
                    if (File.Exists(tempPath))
                    {
                        File.Delete(tempPath);
                    }
                    throw;
                }
            }
        }

        private ImageCodecInfo? GetEncoderInfo(string mimeType)
        {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo codec in codecs)
            {
                if (codec.MimeType == mimeType)
                {
                    return codec;
                }
            }
            return null;
        }
    }
}